﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Twodi.Input.Events;

namespace Twodi.Input
{
    /// <summary>
    /// Objeto que contem informações de input do teclado, utilizando dois estados como meio de controle.
    /// </summary>
    public class KeyboardInput : AbstractInput<KeyboardState, KeyboardEvent>
    {
        /// <summary>
        /// Construtor do Controlador do Teclado.
        /// </summary>
        /// <param name="game">Game associado ao Controlador.</param>
        public KeyboardInput(Game game)
            : base(game)
        {
            State = Keyboard.GetState();
        }

        /// <summary>
        /// Atualizar estados do teclado.
        /// </summary>
        /// <param name="gameTime">Tempo do jogo atual.</param>
        public override void Update(GameTime gameTime)
        {
            SwapStates();
            CallEvents();
            base.Update(gameTime);
        }

        /// <summary>
        /// Invocar eventos.
        /// </summary>
        protected override void CallEvents()
        {
            //Para cada evento dentro da lista de eventos.
            foreach (KeyboardEvent evente in Events)
            {
                //Se evento informa que deve parar o loop, pare.
                if (IsAnyKeyPressed && !evente.Handle(this))
                    break;
            }
        }

        /// <summary>
        /// Trocar estados.
        /// </summary>
        protected override void SwapStates()
        {
            base.SwapStates();
            State = Keyboard.GetState();
        }

        /// <summary>
        /// Alguma tecla pressionada.
        /// </summary>
        public bool IsAnyKeyPressed
        {
            get
            {
                return (State.GetPressedKeys().Length > 0);
            }
        }

        /// <summary>
        /// Tecla Esc foi pressionada e solta.
        /// </summary>
        public bool Escape
        {
            get
            {
                return IsKeyPressed(Keys.Escape);
            }
        }

        /// <summary>
        /// Tecla Enter foi pressionada e solta.
        /// </summary>
        public bool Enter
        {
            get
            {
                return IsKeyPressed(Keys.Enter);
            }
        }


        /// <summary>
        /// Tecla Enter esta sendo pressionada.
        /// </summary>
        public bool Pressing_Enter
        {
            get
            {
                return IsKeyDown(Keys.Enter);
            }
        }

        /// <summary>
        /// Tecla Espaço foi pressionada e solta.
        /// </summary>
        public bool Space
        {
            get
            {
                return IsKeyPressed(Keys.Space);
            }
        }

        /// <summary>
        /// Tecla Espaço esta sendo pressionada.
        /// </summary>
        public bool Pressing_Space
        {
            get
            {
                return IsKeyDown(Keys.Space);
            }
        }

        /// <summary>
        /// Seta para esquerda foi pressionada e solta.
        /// </summary>
        public bool Left
        {
            get
            {
                return IsKeyPressed(Keys.Left);
            }
        }

        /// <summary>
        /// Seta para direita foi pressionada e solta.
        /// </summary>
        public bool Right
        {
            get
            {
                return IsKeyPressed(Keys.Right);
            }
        }

        /// <summary>
        /// Seta para cima foi pressionada e solta.
        /// </summary>
        public bool Up
        {
            get
            {
                return IsKeyPressed(Keys.Up);
            }
        }

        /// <summary>
        /// Seta para baixo foi pressionada e solta.
        /// </summary>
        public bool Down
        {
            get
            {
                return IsKeyPressed(Keys.Down);
            }
        }

        /// <summary>
        /// Seta para esquerda esta sendo pressionada.
        /// </summary>
        public bool LeftPressed
        {
            get
            {
                return IsKeyDown(Keys.Left);
            }
        }

        /// <summary>
        /// Seta para direita esta sendo pressionada.
        /// </summary>
        public bool RightPressed
        {
            get
            {
                return IsKeyDown(Keys.Right);
            }
        }

        /// <summary>
        /// Seta para cima esta sendo pressionada.
        /// </summary>
        public bool UpPressed
        {
            get
            {
                return IsKeyDown(Keys.Up);
            }
        }

        /// <summary>
        /// Seta para baixo esta sendo pressionada.
        /// </summary>
        public bool DownPressed
        {
            get
            {
                return IsKeyDown(Keys.Down);
            }
        }

        /// <summary>
        /// Tecla foi pressionada e agora esta solta.
        /// </summary>
        /// <param name="key">Tecla.</param>
        /// <returns></returns>
        public bool IsKeyUp(Keys key)
        {
            return State.IsKeyUp(key) && OldState.IsKeyDown(key);
        }

        /// <summary>
        /// Tecla esta sendo pressionada.
        /// </summary>
        /// <param name="key">Tecla.</param>
        /// <returns></returns>
        public bool IsKeyDown(Keys key)
        {
            return State.IsKeyDown(key);
        }

        /// <summary>
        /// Tecla foi pressionada e solta.
        /// </summary>
        /// <param name="key">Tecla.</param>
        /// <returns></returns>
        public bool IsKeyPressed(Keys key)
        {
            return State.IsKeyDown(key) && OldState.IsKeyUp(key);
        }

        /// <summary>
        /// Tecla foi pressionada e solta com alguma tecla de alteração.
        /// </summary>
        /// <param name="alterKey">Tecla de alteração (Shift, Alt, Ctrl...).</param>
        /// <param name="key">Tecla.</param>
        /// <returns></returns>
        public bool IsAlterKeyPressed(Keys alterKey, Keys key)
        {
            return IsKeyDown(alterKey) && IsKeyPressed(key);
        }

        /// <summary>
        /// Tecla foi solta com alguma tecla de alteração.
        /// </summary>
        /// <param name="alterKey">Tecla de alteração (Shift, Alt, Ctrl...).</param>
        /// <param name="key">Tecla.</param>
        /// <returns></returns>
        public bool IsAlterKeyUp(Keys alterKey, Keys key)
        {
            return IsKeyDown(alterKey) && IsKeyUp(key);
        }

        /// <summary>
        /// Tecla esta sendo pressionada com alguma tecla de alteração.
        /// </summary>
        /// <param name="alterKey">Tecla de alteração (Shift, Alt, Ctrl...).</param>
        /// <param name="key">Tecla.</param>
        /// <returns></returns>
        public bool IsAlterKeyDown(Keys alterKey, Keys key)
        {
            return IsKeyDown(alterKey) && IsKeyDown(key);
        }
    }
}
